package com.alibaba.citrus.ots.b2b.trade.order.repository.impl;

import com.alibaba.citrus.ots.b2b.trade.order.repository.OrderLineWriteRepository;
import com.alibaba.citrus.ots.b2b.trade.order.repository.request.UpdateFeaturesReq;
import com.alibaba.citrus.ots.common.annotation.EpochTransactional;
import com.alibaba.citrus.ots.common.annotation.RepositoryInvoker;
import com.alibaba.citrus.ots.common.constant.SaleOrderConstants;
import com.alibaba.citrus.ots.common.exception.RepositoryException;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.lattice2.epoch.sdk.model.Result;
import com.epoch.app.bcots.model.dto.GetScItemUnitInfoRequest;
import com.epoch.app.bcots.service.BaseDataService;
import com.epoch.app.otsb2btradecenter.domain.order.dto.UpdateFeaturesResponse;
import com.epoch.app.otsb2btradecenter.domain.order.service.OrderService;
import com.epoch.app.otsb2btradecenter.domain.orderline.dto.*;
import com.epoch.app.otsb2btradecenter.domain.orderline.model.OrderLine;
import com.epoch.app.otsb2btradecenter.domain.orderline.service.OrderLineService;
import com.epoch.app.otsb2btradecenter.enums.OrderStatus;
import com.epoch.app.otsb2btradecenter.model.dto.SelectCombox;
import com.epoch.app.otsb2btradecenter.model.dto.UpdateFeaturesRequest;
import com.epoch.app.otsb2btradecenter.sdo.OrderLineSDO;
import com.epoch.app.otsb2btradecenter.sdo.ScItemSDO;
import com.epoch.app.otsforecastsales.api.forecastorderwrite.service.ForecastOrderWriteService;
import com.epoch.app.otsforecastsales.model.dto.SaleUnit;
import com.epoch.app.otsplatformenhance.service.OtsPlatformEnhanceService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Component
public class OrderLineWriteRepositoryImpl implements OrderLineWriteRepository {

    private static final Log log = Log.getLogger(OrderLineWriteRepositoryImpl.class);

    @Autowired
    private  ForecastOrderWriteService forecastOrderWriteService;

    @Autowired
    private OrderLineService orderLineService;
    @Autowired
    private OrderService orderService;

    @Resource
    private BaseDataService baseDataService;

    @Resource
    private OtsPlatformEnhanceService otsPlatformEnhanceService;

    @Override
    public String batchCreateOrderLine(OrderLineSDO orderLineSDO) {
        OrderLine orderLine = createOrderLineConverter(orderLineSDO);
        CreateOrderLineResponse orderLine1 = orderLineService.createOrderLine(orderLine);
        if (orderLine1.getLastInsertId() == null) {
            log.error("OrderLineWriteRepositoryImpl$batchCreateOrderLine_fail");
        }
        return orderLine1.getLastInsertId();
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public Boolean modifyOrderLine(OrderLineSDO orderLineSDO) {
//        String unitName = getScItemUnitName(orderLineSDO);
        OrderLine orderLine = createOrderLineConverter(orderLineSDO);
//        orderLine.setSaleUnitName(unitName);
        LoadOrderLineRequest loadOrderLineRequest = new LoadOrderLineRequest();
        OrderLine orderLine1 = new OrderLine();
        if (null != orderLine.getId()) {
            loadOrderLineRequest.setId(String.valueOf(orderLine.getId()));
            orderLine1 = orderLineService.loadOrderLine(loadOrderLineRequest);
        }
        orderLine.setSyncVersion(orderLine1.getSyncVersion());

        UpdateOrderLineResponse updateOrderLineResponse = orderLineService.updateOrderLine(orderLine);
        if (updateOrderLineResponse.getCount() != 1) {
            log.error("OrderLineWriteRepositoryImpl$modifyOrderLine_fail");
        }
        return true;
    }

    @Override
    public Boolean batchUpdateOrderLine(String orderId, Integer status) {
        BatchUpdateStatusRequest request = new BatchUpdateStatusRequest();
        request.setMainOrderId(orderId);
        request.setStatus(status);
        orderLineService.batchUpdateStatus(request);
        return true;
    }

    @Override
    @RepositoryInvoker
    public String remove(OrderLineSDO orderLineSDO) {
        DeleteOrderLineRequest deleteOrderLineRequest = new DeleteOrderLineRequest();
        deleteOrderLineRequest.setId(orderLineSDO.getId());
        DeleteOrderLineResponse deleteOrderLineResponse = orderLineService.deleteOrderLine(deleteOrderLineRequest);
        if (deleteOrderLineResponse.getCount() != 1) {
            throw new RuntimeException("delete OrderLineSDO effect rows not 1!");
        }
        return orderLineSDO.getId();
    }

    @Override
    public Boolean modify(OrderLineSDO orderLineSDO) {
        LoadOrderLineRequest loadOrderLineRequest = new LoadOrderLineRequest();
        loadOrderLineRequest.setId(orderLineSDO.getId());
        ScItemSDO scItemSDO = orderLineSDO.getScItemSDO();
        OrderLine orderLine = orderLineService.loadOrderLine(loadOrderLineRequest);
        if (!org.springframework.util.StringUtils.isEmpty(orderLineSDO.getId())) {
            orderLine.setId(Long.parseLong(orderLineSDO.getId()));
        }
        orderLine.setRefuseReasonCode(orderLineSDO.getRefuseReasonCode());
        orderLine.setRemark(orderLineSDO.getRemark());
        orderLine.setInventoryUnitCode(scItemSDO.getInventoryUnitCode());
        orderLine.setInventoryUnit(scItemSDO.getInventoryUnitName());
        if (null != orderLineSDO.getScItemSDO()) {
            orderLine.setQuantity(scItemSDO.getQuantity());
            orderLine.setUnitPrice(scItemSDO.getUnitPrice() == null ? null:scItemSDO.getUnitPrice().toString());
        }
        orderLine.setSaleUnit(scItemSDO.getSaleUnit());
        orderLine.setSaleUnitName(scItemSDO.getSaleUnitName());
        UpdateOrderLineResponse updateOrderLineResponse = orderLineService.updateOrderLine(orderLine);
        if (updateOrderLineResponse.getCount() != 1) {
            throw new RuntimeException("modify OrderLineSDO effect rows not 1!");
        }
        return true;
    }

    @Override
    public String save(OrderLineSDO orderLineSDO) {
        OrderLine orderLine = createOrderLineConverter(orderLineSDO);

        CreateOrderLineResponse orderLine1 = orderLineService.createOrderLine(orderLine);
        if (orderLine1.getLastInsertId() == null) {
            log.error("OrderLineWriteRepositoryImpl$save_fail");
        }
        return orderLine1.getLastInsertId();
    }

    private String getScItemUnitName(OrderLineSDO orderLineSDO) {
        String saleUnitName = null;
        if (null != orderLineSDO.getScItemSDO() && orderLineSDO.getScItemSDO().getScItemId() != null) {
            GetScItemUnitInfoRequest query = new GetScItemUnitInfoRequest();
            query.setScItemId(orderLineSDO.getScItemSDO().getScItemId());
            Map map = (Map) baseDataService.getScItemUnitInfo(query);
            List<SelectCombox> selectComboxes = new ArrayList<>();
            if (map.get("result") != null){
                String js = JSON.toJSONString(map.get("result"));
                List<SaleUnit> saleUnits = JSONArray.parseArray(js,SaleUnit.class);
                if (CollectionUtils.isNotEmpty(saleUnits)){
                    selectComboxes = saleUnits.stream().map(saleUnit -> {
                        SelectCombox selectCombox = new SelectCombox();
                        selectCombox.setLabel(saleUnit.getUnitName()==null?saleUnit.getFeatures():saleUnit.getUnitName());
                        selectCombox.setValue(saleUnit.getUnitCode());
                        selectCombox.setExt(saleUnit.getRelationNum().toString());
                        return selectCombox;
                    }).collect(Collectors.toList());
                }
                Map<String,SelectCombox> stringSelectComboxMap = selectComboxes.stream().collect(Collectors.toMap(SelectCombox::getValue,o->o,(k1,k2)->k2));
                saleUnitName = stringSelectComboxMap.get(orderLineSDO.getScItemSDO().getSaleUnit()).getLabel();
            }
        }
        return saleUnitName;
    }

    @Override
    public Boolean modifyStatus(OrderLineSDO orderLineSDO) {
        LoadOrderLineRequest loadOrderLineRequest = new LoadOrderLineRequest();
        loadOrderLineRequest.setId(orderLineSDO.getId());
        OrderLine orderLine = orderLineService.loadOrderLine(loadOrderLineRequest);
        orderLine.setStatus(orderLineSDO.getStatus());
        orderLine.setDeliveryAmount(orderLineSDO.getDeliveryAmount());
        orderLine.setFeatures(JSON.toJSONString(orderLineSDO.getFeatures()));
        orderLineService.updateOrderLine(orderLine);
        return true;
    }

    @Override
    @RepositoryInvoker
    @EpochTransactional(appCode="ots_b2b_trade_center", dataSourceCode = "cr_ots", dataSourceType = "app")
    public Boolean updateFeatures(UpdateFeaturesReq updateFeaturesReq) {
        if (updateFeaturesReq != null && updateFeaturesReq.getOrderId() != null) {
//            List<Map<String, String>> orderLineFeatures = updateFeaturesReq.getSubOrderFeaturesToUpdate() == null ? null : Lists.newArrayList(updateFeaturesReq.getSubOrderFeaturesToUpdate().values());
            if (MapUtils.isNotEmpty(updateFeaturesReq.getMainOrderFeaturesToUpdate())){
                Map<String, String> mainOrderFeaturesToUpdate = updateFeaturesReq.getMainOrderFeaturesToUpdate();
                UpdateFeaturesRequest request = new UpdateFeaturesRequest();
                request.setId(updateFeaturesReq.getOrderId());
                request.setFeatures(JSON.toJSONString(mainOrderFeaturesToUpdate));
                request.setSyncVersion(updateFeaturesReq.getOrderSyncVersionToCheck());
                UpdateFeaturesResponse affectedRows = this.orderService.updateFeatures(request);
                if (affectedRows.getCount() <= 0L) {
                    log.error("OrderLineWriteRepositoryImpl#updateFeatures_fail");
                    throw new RepositoryException("OTS-05-001-10-16-032");
                }
            }

            if (updateFeaturesReq.getSubOrderFeaturesToUpdate() != null) {
                updateFeaturesReq.getSubOrderFeaturesToUpdate().forEach((orderLineId, featuresToUpdate) -> {
                    if (featuresToUpdate != null) {
                        UpdateFeaturesRequest request = new UpdateFeaturesRequest();
                        request.setId(orderLineId);
                        request.setFeatures(JSON.toJSONString(featuresToUpdate));
                        Map<String,Integer> subOrderVersionMap = updateFeaturesReq.getSubOrderVersionMap();
                        if(subOrderVersionMap != null){
                            request.setSyncVersion(subOrderVersionMap.get(orderLineId));
                        }
                        com.epoch.app.otsb2btradecenter.domain.orderline.dto.UpdateFeaturesResponse aLong = this.orderLineService.updateFeatures(request);
                        if (aLong.getCount() <= 0L) {
                            log.error("OrderLineWriteRepositoryImpl#updateFeatures_fail");
                            throw new RepositoryException("OTS-05-001-10-16-033");
                        }
                    }
                });
            }

        } else {
            throw new RepositoryException("OTS-05-001-10-16-034");
        }


        return true;
    }

//    private OrderLine modifyOrderLineConverter(OrderLineSDO orderLineSDO) {
//        OrderLine orderLine = new OrderLine();
//        if (!org.springframework.util.StringUtils.isEmpty(orderLineSDO.getId())) {
//            orderLine.setId(Long.parseLong(orderLineSDO.getId()));
//        }
//        orderLine.setRefuseReasonCode(orderLineSDO.getRefuseReasonCode());
//        orderLine.setRemark(orderLineSDO.getRemark());
//        orderLine.setInventoryUnit(orderLineSDO.getInventoryUnit());
//        if (null != orderLineSDO.getScItemSDO()) {
//            orderLine.setQuantity(orderLineSDO.getScItemSDO().getQuantity());
//            orderLine.setUnitPrice(orderLineSDO.getScItemSDO().getUnitPrice());
//        }
//        orderLine.setSaleUnit(orderLineSDO.getSaleUnit());
//
//
//        return null;
//    }

    @RepositoryInvoker
    private  OrderLine createOrderLineConverter(OrderLineSDO orderLineSDO) {
        OrderLine orderLine = new OrderLine();
        if (StringUtils.isNotBlank(orderLineSDO.getId())) {
            orderLine.setId(Long.parseLong(orderLineSDO.getId()));
        }
        if (Objects.nonNull(orderLineSDO.getScItemSDO())) {
            orderLine.setScItemOutCode(orderLineSDO.getScItemSDO().getScItemOutCode());
        }

        orderLine.setMainOrderBizId(orderLineSDO.getMainOrderBizId());
        orderLine.setSerialNumber(orderLineSDO.getSerialNumber());
        orderLine.setMainOrderId(orderLineSDO.getMainOrderId());
        orderLine.setOrderLineTag(orderLineSDO.getOrderLineTag());
        orderLine.setBizCode(orderLineSDO.getBizCode());
        orderLine.setOuterOrderLineId(orderLineSDO.getOuterOrderLineId());
        orderLine.setCustomerCode(orderLineSDO.getCustomerCode());
        if (StringUtils.isNotBlank(orderLineSDO.getRefuseReasonCode())) {
            orderLine.setStatus(OrderStatus.COMPLETED.getCode());
            //拒绝后，预报单回退状态，而不是拒绝，属于产品需求变更
//            if (StringUtils.isNotBlank(orderLineSDO.getFrontOrderLineId())) {
//                List<RefuseForecastDetailRequest> requests = new ArrayList<>();
//                RefuseForecastRequest request = new RefuseForecastRequest();
//                RefuseForecastDetailRequest refuseForecastDetailRequest = new RefuseForecastDetailRequest();
//                refuseForecastDetailRequest.setId(orderLineSDO.getFrontOrderLineId());
//                refuseForecastDetailRequest.setRefuseReasonCode(orderLineSDO.getRefuseReasonCode());
//                requests.add(refuseForecastDetailRequest);
//
//                QueryEnumValueSingleRequest queryEnumValueSingleRequest =new QueryEnumValueSingleRequest();
//                queryEnumValueSingleRequest.setCode("refuseReason");
//                queryEnumValueSingleRequest.setValueData(orderLineSDO.getRefuseReasonCode());
//                QueryEnumValueSingleResponse queryEnumValueSingleResponse = otsPlatformEnhanceService.queryEnumValueSingle(queryEnumValueSingleRequest);
//
//                if (Objects.nonNull(queryEnumValueSingleResponse)&&StringUtils.isNotBlank(queryEnumValueSingleResponse.getName())){
//                    refuseForecastDetailRequest.setRefuseReason(queryEnumValueSingleResponse.getName());
//                }
//
//                request.setRefuseForecastDetailRequests(requests);
//                Result<Boolean> booleanResult = forecastOrderWriteService.batchRefuseForecast(request);
//                if (null == booleanResult.getResult()|| booleanResult.getResult().equals(false)) {
//                    throw new RepositoryException("OTS-05-001-10-16-008");
//                }
//            }

        }else{
            orderLine.setStatus(orderLineSDO.getStatus());
        }
        orderLine.setPayStatus(orderLineSDO.getPayStatus());
        orderLine.setPayTime(orderLineSDO.getPayTime());

        ScItemSDO scItemSDO = orderLineSDO.getScItemSDO();

        if (scItemSDO != null) {
            orderLine.setCategoryCode(scItemSDO.getCategoryCode());
            orderLine.setCategoryDesc(scItemSDO.getCategoryDesc());
            orderLine.setCategoryChildCode(scItemSDO.getCategoryChildCode());
            orderLine.setCategoryChildDesc(scItemSDO.getCategoryChildDesc());

            orderLine.setFirstCategoryCode(scItemSDO.getFirstCategoryCode());
            orderLine.setFirstCategoryDesc(scItemSDO.getFirstCategoryDesc());
            orderLine.setSecondCategoryCode(scItemSDO.getSecondCategoryCode());
            orderLine.setSecondCategoryDesc(scItemSDO.getSecondCategoryDesc());
            orderLine.setSaleUnit(scItemSDO.getSaleUnit());
            orderLine.setSaleUnitName(scItemSDO.getSaleUnitName());
            orderLine.setInventoryUnitCode(scItemSDO.getInventoryUnitCode());
            orderLine.setInventoryUnit(scItemSDO.getInventoryUnitName());
            orderLine.setUnitConvert(scItemSDO.getUnitConvert());
            orderLine.setUnitPrice(scItemSDO.getUnitPrice() == null ? null :scItemSDO.getUnitPrice().toString());
            orderLine.setQuantity(scItemSDO.getQuantity());
            orderLine.setActivityPrice(scItemSDO.getActivityPrice() == null ? null :scItemSDO.getActivityPrice().toString());
            orderLine.setScItemId(scItemSDO.getScItemId());
            orderLine.setScItemTitle(scItemSDO.getScItemTitle());
            orderLine.setProductGroupCode(scItemSDO.getProductGroupCode());
            orderLine.setProductGroupName(scItemSDO.getProductGroupName());
            orderLine.setProductationTime(scItemSDO.getProductationTime());
        }
        orderLine.setShouldPayFee(null == orderLineSDO.getShouldPayFee() ? null : orderLineSDO.getShouldPayFee().toString());
        orderLine.setActualPaidFee(null == orderLineSDO.getActualPaidFee() ? null : orderLineSDO.getActualPaidFee().toString());
        orderLine.setDeliveryStatus(orderLineSDO.getDeliveryStatus());
        orderLine.setDeliveryTime(orderLineSDO.getDeliveryTime());
        orderLine.setEndTime(orderLineSDO.getEndTime());
        orderLine.setActivityCode(orderLineSDO.getActivityCode());
        orderLine.setActivityName(orderLineSDO.getActivityName());
        orderLine.setFrontOrderLineId(orderLineSDO.getFrontOrderLineId());
        orderLine.setRemark(orderLineSDO.getRemark());
        orderLine.setSyncVersion(orderLineSDO.getSyncVersion());

        orderLine.setRefuseReasonName(orderLineSDO.getRefuseReasonName());
        orderLine.setRefuseReasonCode(orderLineSDO.getRefuseReasonCode());
        orderLine.setDeliveryAmount(orderLineSDO.getDeliveryAmount());
        orderLine.setGmtCreate(orderLineSDO.getGmtCreate());
        orderLine.setGmtModified(orderLineSDO.getGmtModified() == null? new Date() : orderLineSDO.getGmtModified());
        orderLine.setCreatorId(orderLineSDO.getCreatorId());
        orderLine.setCreatorName(orderLineSDO.getCreatorName());
        orderLine.setModifierId(orderLineSDO.getModifierId());
        orderLine.setModifierName(orderLineSDO.getModifierName());
        orderLine.setReturnCharacter(orderLineSDO.getReturnCharacter());
        orderLine.setOrderLineTag(orderLineSDO.getOrderLineTag());
        orderLine.setCumulativeReceiptQuantity(orderLine.getCumulativeReceiptQuantity());
        orderLine.setCumulativeProcessingQuantity(orderLine.getCumulativeProcessingQuantity());
//        if (orderLineSDO.getFeatures() != null) {
//            StringBuilder sb = new StringBuilder();
//            for (Map.Entry<String, String> entry : orderLineSDO.getFeatures().entrySet()) {
//                sb.append(entry.getKey());
//                sb.append(":");
//                sb.append(entry.getValue());
//                sb.append(";");
//            }
//            orderLine.setFeatures(sb.toString());
//        }
        if (MapUtils.isNotEmpty(orderLineSDO.getFeatures())) {
            String featureStr = JSONObject.toJSONString(orderLineSDO.getFeatures());
            orderLine.setFeatures(featureStr);
        }

        return orderLine;
    }
}
